//TODO: guard
//TODO: text extern "C" with function overloading
//TODO: decorate the MACRO names with Namespaces prefixes

#include <boost/preprocessor/cat.hpp>
#include "for_each_with_separator.hpp"


#define ACTION_PARAMETERS_LIST(SEQ) 			BOOST_PP_TUPLE_ELEM(2,1, BOOST_PP_SEQ_HEAD(SEQ))
#define ACTION_PARAMETERS_LIST_SIGNATURE(SEQ) 	BOOST_PP_TUPLE_ELEM(2,0, BOOST_PP_SEQ_HEAD(SEQ)) BOOST_PP_TUPLE_ELEM(2,1, BOOST_PP_SEQ_HEAD(SEQ))

#define PARAMETERS_LIST(PARAM_SEQ) 				FOR_EACH_WITH_SEPARATOR( PARAM_SEQ, ACTION_PARAMETERS_LIST )
#define PARAMETERS_LIST_SIGNATURE(PARAM_SEQ)	FOR_EACH_WITH_SEPARATOR( PARAM_SEQ, ACTION_PARAMETERS_LIST_SIGNATURE )

#define JNI_FUNCTION_FILLER_0(X, Y)                                \
	((X, Y)) JNI_FUNCTION_FILLER_1
#define JNI_FUNCTION_FILLER_1(X, Y)                                \
	((X, Y)) JNI_FUNCTION_FILLER_0
#define JNI_FUNCTION_FILLER_0_END
#define JNI_FUNCTION_FILLER_1_END

#define JNI_FUNCTION_FILLER(ATTRIBUTES) BOOST_PP_CAT( JNI_FUNCTION_FILLER_0 ATTRIBUTES,_END)

#define JNI_FUNCTION_DETAIL(FUNCTION_NAME, NATIVE_FUNCTION_NAME, RETURN_TYPE, PARAM_SEQ)	\
	RETURN_TYPE FUNCTION_NAME( PARAMETERS_LIST_SIGNATURE(PARAM_SEQ) )						\
	{																						\
		return NATIVE_FUNCTION_NAME															\
		(																					\
			PARAMETERS_LIST(PARAM_SEQ)														\
		);																					\
	}

#define JNI_FUNCTION(FUNCTION_NAME, NATIVE_FUNCTION_NAME, RETURN_TYPE, PARAM_SEQ)			\
	JNI_FUNCTION_DETAIL(FUNCTION_NAME, NATIVE_FUNCTION_NAME, RETURN_TYPE, JNI_FUNCTION_FILLER(PARAM_SEQ))

